package org.internna.ossmoney.model;

import java.util.List;
import java.util.Set;
import java.util.HashSet;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.validation.constraints.NotNull;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.internna.ossmoney.model.security.UserDetails;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.roo.addon.jpa.entity.RooJpaEntity;
import org.springframework.roo.addon.serializable.RooSerializable;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;

@RooJavaBean
@RooSerializable
@RooJpaActiveRecord
@DiscriminatorValue("payee")
@RooJpaEntity(inheritanceType = "SINGLE_TABLE")
@RooToString(excludeFields = {"transactions", "owner"})
public class Payee extends AbstractEntity implements Comparable<Payee> {

	private static final long serialVersionUID = -1837632656616970349L;

	private static final Log logger = LogFactory.getLog(Payee.class);

    @NotNull
    private String name;

    @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, mappedBy = "payee")
    private Set<AccountTransaction> transactions = new HashSet<AccountTransaction>();

    @NotNull
    @ManyToOne(fetch = FetchType.EAGER)
    private UserDetails owner;

    public static Payee findMySelf(UserDetails user) {
        return user != null ? findByName(user.getName()) : null;
    }

    public static Payee findByFinancialInstitution(FinancialInstitution institution) {
        return institution != null ? findByName(institution.getName()) : null;
    }

    public static List<Payee> findByOwner(UserDetails owner) {
    	return entityManager().createQuery("SELECT p FROM Payee p WHERE owner = :owner", Payee.class)
    		.setParameter("owner", owner)
    		.getResultList();
    }

    public static Payee findByName(String name) {
    	UserDetails owner = UserDetails.findCurrentUser();
    	return findByName(name, owner);
    }

    public static Payee findByName(String name, UserDetails owner) {
    	try {
	    	return entityManager().createQuery("SELECT p FROM Payee p WHERE name = :name AND owner = :owner", Payee.class)
	    		.setParameter("name", name)
	    		.setParameter("owner", owner)
	    		.getSingleResult();
    	} catch (RuntimeException re) {
    		logger.warn("Payee [" + name + "] not found in database");
    		return null;
    	}
    }

	@Override public int compareTo(Payee payee) {
		return payee == null ? 1 : name.compareTo(payee.getName());
	}

}
